﻿/*
 * statusmgr.hpp
 *
 *  Created on: 2017年3月27日
 *      Author: work
 */

#ifndef _DM_SCADA_STATUSMGR_HPP_
#define _DM_SCADA_STATUSMGR_HPP_

#include <dm/export.hpp>

#ifndef DM_API_SCADA
#define DM_API_SCADA DM_API_IMPORT
#endif

#include <dm/scada/scada.hpp>
#include <dm/scada/statusinfo.hpp>
#include <dm/scada/statusdescmgr.hpp>

#include <iostream>

namespace dm{
namespace scada{

/**
 * 状态量管理器
 */
class DM_API_SCADA CStatusMgr:protected CScada{
	CStatusMgr( CScada& scada );
public:
	typedef CScada::status_t rt_t;

	static CStatusMgr& ins();

	inline const index_t& size()const{
		return m_cfg.size();
	}

	inline index_t indexById( const id_t& id )const{
		return m_cfg.indexOf(id);
	}

	inline index_t indexByName( const char* name )const{
		return m_cfg.indexOf(name);
	}

	inline index_t indexOfInfo( const SStatusInfo* info )const{
		return m_cfg.indexOf(info);
	}

	index_t indexOfRt( const rt_t* value )const;
	index_t indexOfRt( const volatile rt_t* value )const;

	inline const SStatusInfo* info( const index_t& idx )const{
		return m_cfg.at(idx);
	}

	inline id_t id( const index_t& idx )const{
		const SStatusInfo* p = info(idx);
		return p?p->id:Id_Inv;
	}

	inline const char* name( const index_t& idx )const{
		const SStatusInfo* p = info(idx);
		return p?p->name.c_str():NULL;
	}

	inline const char* desc( const index_t& idx )const{
		const SStatusInfo* p = info(idx);
		return p?p->desc.c_str():"无效索引";
	}

	bool setDesc( const index_t& idx,const char* str );

	inline const SStatusDescInfo* onInfo( const index_t& idx )const{
		const SStatusInfo* p = info(idx);
		return p?CStatusDescMgr::ins().info(p->desc_on):NULL;
	}

	inline const SStatusDescInfo* offInfo( const index_t& idx )const{
		const SStatusInfo* p = info(idx);
		return p?CStatusDescMgr::ins().info(p->desc_off):NULL;
	}

	inline const SStatusDescInfo* invOnInfo( const index_t& idx )const{
		const SStatusInfo* p = info(idx);
		return p?CStatusDescMgr::ins().info(p->desc_invOn):NULL;
	}

	inline const SStatusDescInfo* invOffInfo( const index_t& idx )const{
		const SStatusInfo* p = info(idx);
		return p?CStatusDescMgr::ins().info(p->desc_invOff):NULL;
	}

	inline id_t onId( const index_t& idx )const{
		const SStatusDescInfo* p = onInfo(idx);
		return p?p->id:Id_Inv;
	}

	inline id_t offId( const index_t& idx )const{
		const SStatusDescInfo* p = offInfo(idx);
		return p?p->id:Id_Inv;
	}

	inline id_t invOnId( const index_t& idx )const{
		const SStatusDescInfo* p = invOnInfo(idx);
		return p?p->id:Id_Inv;
	}

	inline id_t invOffId( const index_t& idx )const{
		const SStatusDescInfo* p = invOffInfo(idx);
		return p?p->id:Id_Inv;
	}

	inline const char* onDesc( const index_t& idx )const{
		const SStatusDescInfo* p = onInfo(idx);
		return p?p->desc.c_str():"无效配置";
	}

	inline const char* offDesc( const index_t& idx )const{
		const SStatusDescInfo* p = offInfo(idx);
		return p?p->desc.c_str():"无效配置";
	}

	inline const char* invOnDesc( const index_t& idx )const{
		const SStatusDescInfo* p = invOnInfo(idx);
		return p?p->desc.c_str():"无效配置";
	}

	inline const char* invOffDesc( const index_t& idx )const{
		const SStatusDescInfo* p = invOffInfo(idx);
		return p?p->desc.c_str():"无效配置";
	}

    inline SStatusInfo::ELevel level( const index_t& idx )const{
        const SStatusInfo* p = info(idx);
        return p?p->level:(SStatusInfo::ELevel)(-1);
    }

    bool setLevel( const index_t& idx,const SStatusInfo::ELevel& level );

    bool setFlagSave( const index_t& idx,bool s=true );
    bool setFlagGenTimed( const index_t& idx,bool s=true );
    bool setFlagReportTimed( const index_t& idx,bool s=true );

	const char* valueDesc( const index_t& idx,const CStatus::value_t& value )const;

	index_t deviceIndex( const index_t& idx )const;
	const char* deviceDesc( const index_t& idx )const;

	inline rt_t* rt( const index_t& idx ){
		return (idx<0||idx>=size())?NULL:statuses()+idx;
	}

	inline const rt_t* rt( const index_t& idx )const{
		return (idx<0||idx>=size())?NULL:statuses()+idx;
	}

	inline CStatus::value_t rtValue( const index_t& idx ){
		rt_t* p = rt(idx);
		return p?p->getValue().getValue():0;
	}

	inline CStatus::raw_t rtRaw( const index_t& idx ){
		rt_t* p = rt(idx);
		return p?p->getValue().getRaw():0;
	}

	inline EDataSource rtDs( const index_t& idx ){
		rt_t* p = rt(idx);
		return p?p->getDataSource():ByUnknow;
	}

	inline dm::CTimeStamp rtTs( const index_t& idx ){
		rt_t* p = rt(idx);
		return p?p->getTimeStamp():dm::CTimeStamp();
	}

	const char* rtDesc( const index_t& idx );

	bool update( const index_t& idx,const CStatus& value,const EDataSource& ds,const dm::CTimeStamp& ts=dm::CTimeStamp::cur());

	bool set( const index_t& idx,const CStatus& value,const EDataSource& ds,const dm::CTimeStamp& ts=dm::CTimeStamp::cur() );
	bool gen( const index_t& idx,const CStatus& value,const dm::CTimeStamp& ts=dm::CTimeStamp::cur());

	void printInfo( const index_t& idx,std::ostream& ostr=std::cout )const;
	void printInfoValue( const index_t& idx,std::ostream& ostr=std::cout );

private:
	TCfg<SStatusInfo> m_cfg;
};

}
}

#endif /* INCLUDE_DM_SCADA_STATUSMGR_HPP_ */
